/************************ (C) COPYRIGHT Megahuntmicro *************************
 * File Name            : AT25040B_driver.c
 * Author               : Megahuntmicro
 * Version              : V1.0.0
 * Date                 : 01/23/2015
 * Description          : AT25040B driver.
 *****************************************************************************/
 
/* Include ------------------------------------------------------------------*/
#include "at25040b_driver.h"
/* Private typedef ----------------------------------------------------------*/
/* Private define -----------------------------------------------------------*/	

/* Private macro ------------------------------------------------------------*/	
/* Private variables --------------------------------------------------------*/	

/* Ptivate function prototypes ----------------------------------------------*/	
static uint8_t AT25040B_spi_write(SPI_TypeDef *SPIx,uint8_t write_data);
static uint8_t AT25040B_spi_read(SPI_TypeDef *SPIx,uint8_t *read_data_value);
static uint8_t AT25040B_Write_opcode(SPI_TypeDef *SPIx,uint8_t opcode_value);
/******************************************************************************
* Function Name  : AT25040B_delay
* Description    : Delay
* Input          : delay_counter:delay counter 
* Output         : NONE 
* Return         : NONE
******************************************************************************/
void AT25040B_delay(uint32_t delay_counter)
{
    uint32_t i = delay_counter;
    while (i--);
}
/******************************************************************************
* Function Name  : AT25040B_spi_write
* Description    : At25040B SPI write byte 
* Input          : write_data:write data value
* Output         : NONE
* Return         : state
******************************************************************************/
static uint8_t AT25040B_spi_write(SPI_TypeDef *SPIx,uint8_t write_data)
{ 
    uint8_t state = 0;
    uint16_t u16_time_out_counter = 200;
    SPI_SendData(SPIx, write_data);
    while((RESET == SPI_GetFlagStatus(SPIx, SPI_FLAG_RXNE))&& u16_time_out_counter)
    {
        u16_time_out_counter--;
    }
    if (!u16_time_out_counter)
    {
        state = 1;
    }
    SPI_ReceiveData(SPIx);
    return state;
}
/******************************************************************************
* Function Name  : AT25040B_spi_read
* Description    : At25040B SPI read byte 
* Input          : SPIx: SPI channel,read_data_value:read data store addr
* Output         : NONE
* Return         : state 
******************************************************************************/
static uint8_t AT25040B_spi_read(SPI_TypeDef *SPIx,uint8_t *read_data_value)
{ 
    uint8_t state = 0;
    uint16_t u16_time_out_counter = 200;
    SPI_SendData(SPIx, 0xFF);
    while((RESET == SPI_GetFlagStatus(SPIx, SPI_FLAG_RXNE))&& u16_time_out_counter)
    {
        u16_time_out_counter--;
    }
    if (!u16_time_out_counter)
    {
        state = 1;
    }
    *read_data_value = SPI_ReceiveData(SPIx);
    return state;
}
/******************************************************************************
* Function Name  : AT25040B_Write_opcode
* Description    : write opcode
* Input          : opcode_value:opcode num
* Output         : NONE 
* Return         : state
******************************************************************************/
static uint8_t AT25040B_Write_opcode(SPI_TypeDef *SPIx,uint8_t opcode_value)
{
    uint8_t state = 0;
    GPIO_ResetBits(CS_PORT,CS_PIN);
    AT25040B_delay(200);
    state = AT25040B_spi_write(SPIx, opcode_value);
    AT25040B_delay(200);
    GPIO_SetBits(CS_PORT,CS_PIN);
    return state;
}
/******************************************************************************
* Function Name  : AT25040B_Write_byte
* Description    : write data to AT25040B
* Input          : start_addr: Write start addr; write_byte: write data value 
* Output         : NONE 
* Return         : state
******************************************************************************/
uint8_t AT25040B_Write_byte(SPI_TypeDef *SPIx, uint16_t start_addr, uint8_t write_byte)
{
    uint8_t state = 0;
    uint8_t opcode = 0;
    /* */
    opcode = WRITE | ((start_addr & 0x100) >> 5);
    /* Set write enable latch */
    state = AT25040B_Write_opcode(SPIx, WREN);
    if (state)
    {
        return state;
    }
    /* Write data to EEPROM */
    GPIO_ResetBits(CS_PORT,CS_PIN);                   /* cs is low */
    AT25040B_delay(200);
    /* Write WRITE opcode and addr(A8 bit) */
    state = AT25040B_spi_write(SPIx,opcode);
    if (state)
    {
        GPIO_SetBits(CS_PORT,CS_PIN);
        return state;
    }
    /* Write start address */
    state = AT25040B_spi_write(SPIx,(uint8_t)(start_addr & 0xFF));
    if (state)
    {
        GPIO_SetBits(CS_PORT,CS_PIN);
        return state;
    }
    /* Write data */
    state = AT25040B_spi_write(SPIx,write_byte);
    if (state)
    {
        GPIO_SetBits(CS_PORT,CS_PIN);
        return state;
    }
    AT25040B_delay(200);
    GPIO_SetBits(CS_PORT,CS_PIN);                     /* cs is high */
    return state;
}
/******************************************************************************
* Function Name  : AT25040B_Write_Mulitbyte
* Description    : write mulitdata to AT25040B
* Input          : start_addr: Write start addr; write_byte: write data value
*                  Buf: ready to be written data start addr;
*                  write_data_num: write data number
* Output         : NONE 
* Return         : state
******************************************************************************/
uint8_t AT25040B_Write_Mulitbytes(SPI_TypeDef *SPIx, 
                                 uint16_t start_addr, 
                                 uint8_t *Buf,
                                 uint32_t write_data_num)
{
    uint8_t state = 0;
    uint8_t opcode = 0;
    /* */
    opcode = WRITE | ((start_addr & 0x100) >> 5);
    /* Set write enable latch */
    state = AT25040B_Write_opcode(SPIx, WREN);
    if (state)
    {
        return state;
    }
    /* Write data to EEPROM */
    GPIO_ResetBits(CS_PORT,CS_PIN);                   /* cs is low */
    AT25040B_delay(200);
    /* Write WRITE opcode and addr(A8 bit) */
    state = AT25040B_spi_write(SPIx,opcode);
    if (state)
    {
        GPIO_SetBits(CS_PORT,CS_PIN);
        return state;
    }
    /* Write start address */
    state = AT25040B_spi_write(SPIx,(uint8_t)(start_addr & 0xFF));
    if (state)
    {
        GPIO_SetBits(CS_PORT,CS_PIN);
        return state;
    }
    /* Write data */
    while (write_data_num--)
    {
        /* Write start address */
        state = AT25040B_spi_write(SPIx,*Buf++);
        if (state)
        {
            GPIO_SetBits(CS_PORT,CS_PIN);
            return state;
        }
    }
    AT25040B_delay(200);
    GPIO_SetBits(CS_PORT,CS_PIN);                     /* cs is high */
    return state;
}
/******************************************************************************
* Function Name  : AT25040B_read_byte
* Description    : read data from AT25040B
* Input          : start_addr: Read start addr; read_data_value:read data store addr
* Output         : NONE 
* Return         : state
******************************************************************************/
uint8_t AT25040B_read_byte(SPI_TypeDef *SPIx, uint16_t start_addr,uint8_t *read_data_value)
{
    uint8_t state = 0;
    uint8_t opcode = 0;
    opcode = READ | ((start_addr & 0x100) >> 5);
    /* read data from EEPROM */
    GPIO_ResetBits(CS_PORT,CS_PIN);                   /* cs is low */
    AT25040B_delay(200);
    /* Write WRITE opcode and addr(A8 bit) */
    state = AT25040B_spi_write(SPIx,opcode);
    if (state)
    {
        GPIO_SetBits(CS_PORT,CS_PIN);
        return state;
    }
    /* Read start address */
    state = AT25040B_spi_write(SPIx,(uint8_t)(start_addr & 0xFF));
    if (state)
    {
        GPIO_SetBits(CS_PORT,CS_PIN);
        return state;
    }
    /* Read data */
    state = AT25040B_spi_read(SPIx,read_data_value);
    if (state)
    {
        GPIO_SetBits(CS_PORT,CS_PIN);
        return state;
    }
    AT25040B_delay(200);
    GPIO_SetBits(CS_PORT,CS_PIN);                     /* cs is high */
    return state;
}
/******************************************************************************
* Function Name  : AT25040B_Write_Mulitread
* Description    : read mulitdata from AT25040B
* Input          : start_addr: read start addr; write_byte: read data value
*                  Buf: read data store start addr;
*                  read_data_num: read data number
* Output         : NONE 
* Return         : state
******************************************************************************/
uint8_t AT25040B_Read_Mulitbytes(SPI_TypeDef *SPIx, 
                                 uint16_t start_addr, 
                                 uint8_t *Buf,
                                 uint32_t read_data_num)
{
    uint8_t state = 0;
    uint8_t opcode = 0;
    /* */
    opcode = READ | ((start_addr & 0x100) >> 5);
    /* Read data from EEPROM */
    GPIO_ResetBits(CS_PORT,CS_PIN);                   /* cs is low */
    AT25040B_delay(200);
    /* Write WRITE opcode and addr(A8 bit) */
    state = AT25040B_spi_write(SPIx,opcode);
    if (state)
    {
        GPIO_SetBits(CS_PORT,CS_PIN);
        return state;
    }
    /* read start address */
    state = AT25040B_spi_write(SPIx,(uint8_t)(start_addr & 0xFF));
    if (state)
    {
        GPIO_SetBits(CS_PORT,CS_PIN);
        return state;
    }
    /* read data */
    while (read_data_num--)
    {
        /* read start address */
        state = AT25040B_spi_read(SPIx,Buf++);
        if (state)
        {
            GPIO_SetBits(CS_PORT,CS_PIN);
            return state;
        }
    }
    AT25040B_delay(200);
    GPIO_SetBits(CS_PORT,CS_PIN);                     /* cs is high */
    return state;
}
/************************ (C) COPYRIGHT 2014 Megahuntmicro ****END OF FILE****/